<!DOCTYPE html>
<html lang="zh">

	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>地图</title>
		<link rel="stylesheet" href="lib/bootstrap.min.css">
		<link rel="stylesheet" href="css/style.css">
		<script src="https://lib.baomitu.com/socket.io/2.0.1/socket.io.js"></script>
		<!--<script src="js/math.js" type="text/javascript" charset="utf-8"></script>-->
		<!--<script src="util/jibu.js" type="text/javascript" charset="utf-8"></script>-->

	</head>

	<body>
		<div id="fengMap"></div>
		<!-- 视角按钮组 -->
		<div class="viewmode-group btn-group-vertical" data-toggle="buttons">
			<button class="btn btn-default">2D</button>
			<button class="btn btn-default btn-primary">3D</button>
			<button id="system">ios</button>
			<button id="time_cha">222</button>
			<button id="beaconX">0</button>
			<button id="beaconY">0</button>
			
		</div>

		<script src="lib/jquery-2.1.4.min.js"></script>
		<script src="util/math.js" type="text/javascript" charset="utf-8"></script>
		<script src="util/km.js?a=25" type="text/javascript" charset="utf-8"></script>
		<script src="lib/fengmap.min.js"></script>
		<!--<script src="util/util.js" type="text/javascript" charset="utf-8"></script>-->

		<script type="text/javascript">
			var XYobj = {};
			let _qValue = 1; //0 完全相信pdr 1完全相信蓝牙
			let _rValue = 1;
			var sportState = 0; //运动状态 0 运动 1静止（拽）2静止（不拽）
			var clearTimeoutId0, clearTimeoutId1, clearIntervalMessageId; //idclearTimeoutId0,  //id
			var currentTime, lastTime, timeCount;

			function getQueryString(name) {
				var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
				var r = window.location.search.substr(1).match(reg);
				if(r != null) return unescape(r[2]);
				return null;
			}

			var resultX = 31;
			var resultY = 12;

			var zhuanhuanXY; //地图坐标

			var Ldirection = 180; //浏览器方向

			var newCoord = {
				x: 0,
				y: 0
			}
			var locationCount = 0;

			//获取版本号,设置title
			document.title = '室内定位' + fengmap.VERSION;

			//定义全局map变量
			var map;
			var fmapID = 'location-test';
			var locationMarker;
			//楼层ID
			var lastGid = null;
			//第一人称、第三人称控制开关；定位跟随开关
			var others = true;
			var getData = {
				x: 14,
				y: 2
			}
			var layer = null
			var resultData = CoordTransform(getData)

			window.onload = function() {
				map = new fengmap.FMMap({
					//渲染dom
					container: document.getElementById('fengMap'),
					//地图数据位置
					mapServerURL: './data/' + fmapID,
					//主题数据位置
					mapThemeURL: 'data/theme/',
					//设置主题
					defaultThemeName: '2001',
					// 默认比例尺级别设置为20级
					defaultMapScaleLevel: 22,
					//开启2维，3维切换的动画显示
					viewModeAnimateMode: true,
					//方向枚举型。可设置正南、正北、正东、正西、东南、西南等方向值。具体可参考fengmap.ControlsPoseEnum类。NORTH WEST SOUTH
					defaultControlsPose: fengmap.FMDirection.NORTH,
					defaultViewMode: fengmap.FMViewMode.MODE_2D, //初始二维还是三维状态，三维状态为MODE_3D,

					//开发者申请应用下web服务的key
					key: '670072019dff394f3f991e88e98024d5',
					//开发者申请应用名称
					appName: 'innerMap',
				});

				//打开Fengmap服务器的地图数据和主题
				map.openMapById(fmapID);

				//显示指北针
				map.showCompass = true;
				//地图加载完成回调
				map.on('loadComplete', function() {

					addlocationMarker(resultX, resultY);
					//转换后的地图坐标
					FengZhuangXY();

					WebSocketTest();

				});

				var aBtn = document.querySelectorAll('.btn');
				//开启2维模式
				aBtn[0].onclick = function() {
					//设置地图为2维模式
					map.viewMode = fengmap.FMViewMode.MODE_2D;
					this.classList.add('btn-primary');
					aBtn[1].classList.remove('btn-primary');
				};

				//开启3维模式
				aBtn[1].onclick = function() {
					//设置地图为3维模式
					map.viewMode = fengmap.FMViewMode.MODE_3D;
					this.classList.add('btn-primary');
					aBtn[0].classList.remove('btn-primary');
				};

				//添加定位点图层
				function addlocationMarker(coord) {
					locationMarker = new fengmap.FMLocationMarker({
						//设置图片的路径
						url: 'image/pointer.png',
						//设置图片显示尺寸
						size: 46,
						//设置图片高度
						height: 1,
					});
					//添加定位点标注
					map.addLocationMarker(locationMarker);
					//设置定位图标位置
					setLocationMakerPosition();

					return locationMarker;
				};

				//设置图片标注点位置信息
				function setLocationMakerPosition(angle, direction) {
					var zhuanXY = {
						x: resultX,
						y: resultY,
					}
					var coord = CoordTransform(zhuanXY);
					var data = {
						//设置定位点的x坐标
						x: coord.x,
						//设置定位点的y坐标
						y: coord.y,
						//设置定位点所在楼层
						groupID: coord.groupID,
						time: .50,
						callback: function() {
							//回调函数
						},
						zOffset: 1
					};
					//设置定位图标旋转角度
					if(direction) {
						locationMarker.rotateTo(-direction);
						if(others) {
							map.rotateTo({
								to: direction,
								time: 1
							});
						}
					}
					//不同楼层
					if(lastGid !== coord.groupID) {
						lastGid = coord.groupID;
						locationMarker.setPosition(data);
					}
					locationMarker.moveTo(data);
					map.moveTo({
						x: coord.x,
						y: coord.y,
						groupID: coord.groupID,
						time: 1
					});
				}

				//计步定位
				function FengZhuangXY() {

					//状态：静止
					var STAY = 0;
					//状态：运动
					var MOVE = 1;
					//运动状态判断数组，长度20
					var stateValue = new Array(20).fill(0);
					//加速度数组  长度100
					var Accs = new Array(100).fill(0);;
					//每次传入加速度的时间，省去定时器 长度100
					var time = new Array(100).fill(0);
					//数组下标
					var count = 0;
					//行走步数
					var Step = 0;
					//步长
					var Length = 0;

					//行进距离
					var Distance = 0;
					var RDistance = 0;
					//状态
					var State = STAY;

					var AccelerometerX, AccelerometerY, AccelerometerZ; //加速计三个方向的数据
					var count = 0;
					var responseObj = {};
					var wobushu;

//					try {
//						window.addEventListener("deviceorientation", orientationHandler, false);
//
//						function orientationHandler(event) {
//							Ldirection = Math.round(event.webkitCompassHeading);
//							Ldirection += 135;
//							Ldirection += 180;
//							if(Ldirection > 360) {
//								Ldirection -= 360;
//							}
//							alert(cDirection)
//							setLocationMakerPosition(null, Ldirection);
//						}
//					} catch(e) {
//
//					}

					
					try {
						window.addEventListener("deviceorientationabsolute", orientationHandler, false);

						function orientationHandler(event) {

							Ldirection = 360 - Math.round(event.alpha); //顺时针0——360增大
//							Ldirection = Ldirection + initLdirection;
//							Ldirection = Math.round(event.alpha);
							Ldirection += 135;
							Ldirection += 180;
							if(Ldirection > 360) {
								Ldirection -= 360;
							}

							setLocationMakerPosition(null, Ldirection);
						}
					} catch(e) {

					}

					if(window.DeviceMotionEvent) {
						window.addEventListener('devicemotion', deviceMotionHandler, false);
					}
					var vibrateSupport = "vibrate" in navigator
					if(vibrateSupport) { //兼容不同的浏览器
						navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
					}

					function deviceMotionHandler(eventData) {
						var acceleration = eventData.accelerationIncludingGravity;
						AccelerometerX = acceleration.x;
						AccelerometerY = acceleration.y;
						AccelerometerZ = acceleration.z;
						//						var currentTime = getCurrentTime();
						var valuesArray = [acceleration.x, acceleration.y, acceleration.z];

						if(!lastTime) {
							lastTime = new Date().getTime();
						}
						currentTime = new Date().getTime();
						let timeCha = currentTime - lastTime;
						let time_cha_el = document.getElementById("time_cha");
						time_cha_el.innerHTML = timeCha;

						if(timeCha > 2500) {
							_qValue = 0.001;
							_rValue = 0.01;
						} else {
							_qValue = 0;
							_rValue = 1;
						}

						refreshAcc(valuesArray, currentTime);
					}

					function refreshAcc(values, timestamp) {
						Accs[count] = Math.sqrt(values[0] * values[0] + values[1] * values[1] + values[2] * values[2]);
						time[count] = timestamp;
						//检查运动状态
						stateValue[count % 20] = Accs[count];
						checkState();
						//设置检测点，检测点的值为到最新数据的距离，如果太近了将无法确定其为波峰波谷
						//检测点的作用是来减少计算量
						var ckpoint = Accs.length / 5;
						//运动状态判断加上判断检测点是否有波谷存在
						if(State == MOVE && Accs[(count - ckpoint + Accs.length) % Accs.length] < Accs[(count - ckpoint + Accs.length + 1) % Accs.length] &&
							Accs[(count - ckpoint + Accs.length) % Accs.length] <
							Accs[(count - ckpoint + Accs.length - 1) % Accs.length]) {
							//求均值
							var ave0 = 0;
							for(var i = 0; i < Accs.length; ++i) {
								ave0 += Accs[i];
							}
							ave0 /= Accs.length;
							//调整数组顺序，把新数据放在前面，同时把数据减去均值

							var data = new Array(Accs.length).fill(0);
							for(var i1 = 0, j = count; i1 < data.length; ++i1, --j) {
								if(j < 0) {
									j += data.length
								};
								data[i1] = Accs[j] - ave0;
							}
							//寻找波峰波谷
							var sign = new Array(Accs.length).fill(0);
							for(var i2 = 1; i2 < Accs.length - 1; ++i2) {
								if(Math.abs(data[i2]) > 0.8 &&
									Math.abs(2 * data[i2]) > Math.abs((data[i2 - 1] + data[i2 + 1]))) {
									if(data[i2] > 0) {
										sign[i2] = 1;
									} else {
										sign[i2] = -1;
									}
								}
							}

							for(var i3 = 1; i3 < sign.length - 1;) {
								var idx = i3;
								while(++i3 < sign.length - 1 &&
									(sign[i3] == 0 || sign[i3] == sign[idx])) {
									if(sign[i3] != 0 && Math.abs(data[i3]) > Math.abs(data[idx])) {
										sign[idx] = 0;
										idx = i3;
									} else {
										sign[i3] = 0;
									}
								}
							}
							//再次判断检测点是否是波谷
							if(sign[ckpoint] < 0) {
								var index = ckpoint;
								//寻找下个波峰
								while(++index < sign.length && sign[index] == 0);
								if(index < sign.length && sign[index] > 0) {
									var peak = index;
									//寻找下个波谷
									while(++index < sign.length && sign[index] == 0);
									if(index < sign.length && sign[index] < 0) {
										var valley = index;
										//计算H和T
										var H = data[peak] - 0.5 * data[ckpoint] - 0.5 * data[valley];
										var T = time[(count - ckpoint + time.length) % time.length] - time[(count - valley + time.length) % time.length];

										//门限判决
										//if(H > 3 && T > 300 && T < 1400) {

										if(H > 1 && T > 300 && T < 1400) {
											//											alert(2)
											_qValue = 0; 
											_rValue = 1;
											lastTime = new Date().getTime();

											//步长计算
											var steplength = 0.35 - 0.000155 * T + 0.1638 * Math.sqrt(H);
											//var steplength = 0.65 - 0.000155 * T + 0.1638 * Math.sqrt(H);
											Length = (Length + steplength) / 2;
											Distance += steplength;
											++Step;

											//做卡尔曼
											var finalXY = suanXY(resultX, resultY, steplength, Ldirection, XYobj.x, XYobj.y, _qValue, _rValue)
											resultX = finalXY._data[0][0];
											resultY = finalXY._data[1][0];
											setLocationMakerPosition(null, Ldirection)
										}
									}
								}
							}
						}
						if(++count == 100) count = 0;

					}

					//检查运动状态
					function checkState() {
						var ave = 0;
						var Var = 0;
						//求均值
						for(var i = 0; i < stateValue.length; i++) {
							ave += stateValue[i];
						}
						ave /= stateValue.length;
						//求方差
						for(var i = 0; i < stateValue.length; i++) {
							Var += (stateValue[i] - ave) * (stateValue[i] - ave);
						}
						Var /= stateValue.length;
						//状态判决
						State = Var > 0.1 ? MOVE : STAY;
					}

					//获取当前时间戳
					function getCurrentTime() {
						var timestamp = new Date().getTime();
						return timestamp;
					}

				}

				function WebSocketTest() {
					if("WebSocket" in window) {
						var ws = new WebSocket("wss://www.dowino2o.net:8087/api/websocket?openId=map" + 123456);
						ws.onopen = function() {
							setInterval(function() {
								ws.send("保持心跳");
							}, 50000)
						};

						ws.onmessage = function(evt) {
							var received_msg = evt.data;
							console.log('收到消息：', received_msg);
							try {
								var jsonObj = JSON.parse(received_msg);
								XYobj = jsonObj;
								//在页面上显示websocket传送过来的坐标
								let beaconX = document.getElementById("beaconX");
								let beaconY = document.getElementById("beaconY");
								
								beaconX.innerHTML = XYobj.x;
								beaconY.innerHTML = XYobj.y;
								
								//做卡尔曼
								var finalXY = suanXY(resultX, resultY, 0, Ldirection, XYobj.x, XYobj.y, _qValue, _rValue)
								resultX = finalXY._data[0][0];

								resultY = finalXY._data[1][0];
								console.log('finalXY', finalXY)
								setLocationMakerPosition(null, Ldirection)

								//收到质心坐标 分多次做卡尔曼定位
								//								if(clearIntervalMessageId) {
								//									clearInterval(clearIntervalMessageId);
								//								}
								//								clearIntervalMessageId = setInterval(function() {
								//									
								//								}, 800)

							} catch(err) {
								console.log('err', err)
							}

						};

						ws.onclose = function() {
							// 关闭 websocket
							console.log('连接已关闭')
							
						};
					} else {
						// 浏览器不支持 WebSocket
						alert("您的浏览器不支持 WebSocket!");
					}
				}

			};

			function CoordTransform(Coord) {
				//创建转换器
				var trasformer = new fengmap.MapCoordTransform();
				//来至定位系统的参数 定位的原点坐标 已经定位的范围,(矩形对角线的2个点)
				var locOrigion = {
					'x': 0,
					'y': 0
				}; //定位坐标原点
				var locRange = {
					'x': 32.387,
					'y': 32.202
				}; //定位范围

				//根据定位四个角点的地图坐标点
				var mapParas = [];
				mapParas[0] = {
					'x': 13028246.2666,
					'y': 4737041.5179
				}; //定位原点地图坐标
				mapParas[1] = {
					'x': 13028214.5795,
					'y': 4737041.5179
				}; //X轴终点地图坐标
				mapParas[2] = {
					'x': 13028214.5702,
					'y': 4737009.6396
				}; //定位原点对角点地图坐标
				mapParas[3] = {
					'x': 13028246.2666,
					'y': 4737009.6302
				}; //Y轴终点地

				//转换器初始化
				trasformer.init(locOrigion, locRange, mapParas);

				//定位系统中的定位坐标
				var loc = {
					'x': Coord.x,
					'y': Coord.y
				}; //定位系统所返回的坐标点

				//转换后的地图坐标
				var mapCoord = trasformer.transform(loc);
				return mapCoord;
			}
		</script>
	</body>

</html>